﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace FineSoft.Controls
{
	public class ProgressiveImage : System.Windows.Controls.Image
	{
		public string ImageUrl
		{
			get
			{
				return (string)GetValue(ImageUrlProperty);
			}
			set
			{
				SetValue(ImageUrlProperty, value);
			}
		}

		// Using a DependencyProperty as the backing store for ImageUrl.  This enables animation, styling, binding, etc...
		public static readonly System.Windows.DependencyProperty ImageUrlProperty =
			System.Windows.DependencyProperty.Register("ImageUrl", typeof(string), typeof(ProgressiveImage), new System.Windows.UIPropertyMetadata(null, ImageUrl_Changed));

		protected static void ImageUrl_Changed(System.Windows.DependencyObject d, System.Windows.DependencyPropertyChangedEventArgs e)
		{
			ProgressiveImage image = (ProgressiveImage)d;
			if (image._BackgroundWorker != null)
			{
				image._BackgroundWorker.CancelAsync();
				image._BackgroundWorker = null;
			}
			image.BackgroundWorker.RunWorkerAsync(e.NewValue);
		}

		private System.ComponentModel.BackgroundWorker _BackgroundWorker;
		protected System.ComponentModel.BackgroundWorker BackgroundWorker
		{
			get
			{
				if (this._BackgroundWorker == null)
				{
					this._BackgroundWorker = new System.ComponentModel.BackgroundWorker();
					this._BackgroundWorker.WorkerReportsProgress = true;
					this._BackgroundWorker.DoWork += new System.ComponentModel.DoWorkEventHandler(BackgroundWorker_DoWork);
					this._BackgroundWorker.ProgressChanged += new System.ComponentModel.ProgressChangedEventHandler(BackgroundWorker_ProgressChanged);
				}
				return this._BackgroundWorker;
			}
		}

		//private System.Net.WebClient _WebClient;
		//protected System.Net.WebClient WebClient
		//{
		//    get
		//    {
		//        if (this._WebClient == null)
		//        {
		//            this._WebClient = new System.Net.WebClient();
		//            this._WebClient.DownloadProgressChanged += new System.Net.DownloadProgressChangedEventHandler(_WebClient_DownloadProgressChanged);
		//        }
		//        return this._WebClient;
		//    }
		//}

		private static System.TimeSpan? _ThreeSeconds;
		protected System.TimeSpan ThreeSeconds
		{
			get
			{
				if (_ThreeSeconds == null)
					_ThreeSeconds = new TimeSpan(0, 0, 3);
				return _ThreeSeconds.Value;
			}
		}

		public event System.EventHandler ImageLoaded;
		protected void OnImageLoaded()
		{
			if (this.ImageLoaded != null)
				this.ImageLoaded(this, System.EventArgs.Empty);
		}

		void BackgroundWorker_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
		{
			string url = (string)e.Argument;
			if (string.IsNullOrEmpty(url))
			{
				this.Source = null;
				return;
			}

			System.Net.WebRequest request = System.Net.WebRequest.Create(url);
			System.IO.Stream stream = request.GetResponse().GetResponseStream();
			System.Collections.Generic.List<byte> imageSource = new List<byte>();
			byte[] bytes = new byte[1024 * 10];
			int count;
			System.DateTime start = System.DateTime.Now;
			while ((count = stream.Read(bytes, 0, bytes.Length)) > 0)
			{
				imageSource.AddRange(bytes.Take(count));
				System.DateTime now = System.DateTime.Now;
				if (now - start < this.ThreeSeconds)
					continue;
				start = now;
				if (e.Cancel)
					return;
				this.BackgroundWorker.ReportProgress(0, imageSource.ToArray());
			}
			if (e.Cancel)
				return;
			try
			{
				if (((System.IO.MemoryStream)((System.Windows.Media.Imaging.BitmapImage)this.Source).StreamSource).Length == imageSource.Count)
					return;
				this.BackgroundWorker.ReportProgress(0, imageSource.ToArray());
			}
			finally
			{
				this.OnImageLoaded();
			}
		}

		void BackgroundWorker_ProgressChanged(object sender, System.ComponentModel.ProgressChangedEventArgs e)
		{
			System.Windows.Media.Imaging.BitmapImage image = new System.Windows.Media.Imaging.BitmapImage();
			image.BeginInit();
			image.StreamSource = new System.IO.MemoryStream(((byte[])e.UserState).ToArray());
			image.EndInit();
			this.Source = image;
		}

		//void WebClient_DownloadProgressChanged(object sender, System.Net.DownloadProgressChangedEventArgs e)
		//{
		//    if (e.Cancelled)
		//        return;
		//    this.BackgroundWorker.ReportProgress(0, e.Result);
		//}

		//void WebClient_DownloadDataCompleted(object sender, System.Net.DownloadDataCompletedEventArgs e)
		//{
		//}
	}
}